#include "sdk.h"
#include "examinememorydlg.h"
#include "debuggermanager.h"

BEGIN_EVENT_TABLE( ExamineMemoryDlg, wxPanel )
  EVT_BUTTON( XRCID( "btnGo" ), ExamineMemoryDlg::OnGo )
  EVT_COMBOBOX( XRCID( "cmbBytes" ), ExamineMemoryDlg::OnGo )
  EVT_TEXT_ENTER( XRCID( "txtAddress" ), ExamineMemoryDlg::OnGo )
END_EVENT_TABLE()

ExamineMemoryDlg::ExamineMemoryDlg( wxWindow* parent ) : m_LastRowStartingAddress( 0 ) {
  wxXmlResource* xml_res = wxXmlResource::Get();
  wxString resPath = ConfigManager::GetDataFolder() + _T( "/memdump.xrc" );
  if( !xml_res->Load( resPath ) )  {
    xml_File_lock = false;
    Manager::Get()->GetLogManager()->LogInf( F( _T( "文件丢失: %s " ), resPath.wx_str() ) );
    return;
  }
  if( !xml_res->LoadPanel( this, parent, _T( "MemoryDumpPanel" ) ) ) {
    xml_File_lock = false;
    Manager::Get()->GetLogManager()->LogInf( _T( "资源丢失" ) );
    return;
  }
  xml_File_lock = true;
  m_pText = XRCCTRL( *this, "txtDump", wxTextCtrl );
  wxFont font( 8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL );
  m_pText->SetFont( font );
  ConfigManager *c = Manager::Get()->GetConfigManager( _T( "debugger_common" ) );
  int bytes = c->ReadInt( _T( "/common/examine_memory/size_to_show" ), 32 );
  wxString strBytes;
  strBytes << bytes;
  wxComboBox *combo = XRCCTRL( *this, "cmbBytes", wxComboBox );
  if( !combo->SetStringSelection( strBytes ) ) {
    combo->SetSelection( 1 );
  }
  Clear();
}

void ExamineMemoryDlg::Begin() {
  m_pText->Freeze();
}

void ExamineMemoryDlg::End() {
  m_pText->Thaw();
}

void ExamineMemoryDlg::Clear() {
  m_pText->Clear();
  m_LastRowStartingAddress = 0;
  m_ByteCounter = 0;
  for( int i = 0; i < 67; ++i ) {
    m_LineText[i] = _T( ' ' );
  }
}

wxString ExamineMemoryDlg::GetBaseAddress() {
  return XRCCTRL( *this, "txtAddress", wxTextCtrl )->GetValue();
}

int ExamineMemoryDlg::GetBytes() {
  long a;
  XRCCTRL( *this, "cmbBytes", wxComboBox )->GetValue().ToLong( &a );
  return a;
}

void ExamineMemoryDlg::AddError( const wxString& err ) {
  m_pText->AppendText( err + _T( '\n' ) );
}

void ExamineMemoryDlg::AddHexByte( const wxString& addr, const wxString& hexbyte ) {
  int bcmod = m_ByteCounter % 16;
  if( m_LastRowStartingAddress == 0 ) {
    addr.ToULong( &m_LastRowStartingAddress, 16 );
  }
#define HEX_OFFSET(a) (a*3)
#define CHAR_OFFSET(a) (16*3 + 3 + a)
  unsigned long hb;
  hexbyte.ToULong( &hb, 16 );
  m_LineText[HEX_OFFSET( bcmod )] = hexbyte[0];
  m_LineText[HEX_OFFSET( bcmod ) + 1] = hexbyte[1];
  m_LineText[CHAR_OFFSET( bcmod )] = hb >= 32 ? wxChar( hb ) : wxChar( _T( '.' ) );
  ++m_ByteCounter;
  if( m_ByteCounter != 0 && m_ByteCounter % 16 == 0 ) {
    if( m_ByteCounter != 16 ) {
      m_pText->AppendText( _T( '\n' ) );
    }
    m_LineText[23] = _T( '|' );
    unsigned long a;
    addr.ToULong( &a, 16 );
    m_pText->AppendText( F( _T( "0x%lx: %.67s" ), m_LastRowStartingAddress, m_LineText ) );
    for( int i = 0; i < 67; ++i ) {
      m_LineText[i] = _T( ' ' );
    }
    m_LastRowStartingAddress = a + 8;
  }
}

void ExamineMemoryDlg::OnGo( M_Code_unused wxCommandEvent& event ) {
  cbDebuggerPlugin *plugin = Manager::Get()->GetDebuggerManager()->GetActiveDebugger();
  ConfigManager *c = Manager::Get()->GetConfigManager( _T( "debugger_common" ) );
  c->Write( _T( "/common/examine_memory/size_to_show" ), GetBytes() );
  if( plugin ) {
    plugin->RequestUpdate( cbDebuggerPlugin::ExamineMemory );
  }
}

void ExamineMemoryDlg::EnableWindow( bool enable ) {
  Enable( enable );
}

void ExamineMemoryDlg::SetBaseAddress( const wxString &addr ) {
  XRCCTRL( *this, "txtAddress", wxTextCtrl )->SetValue( addr );
  cbDebuggerPlugin *plugin = Manager::Get()->GetDebuggerManager()->GetActiveDebugger();
  if( plugin ) {
    plugin->RequestUpdate( cbDebuggerPlugin::ExamineMemory );
  }
}
